

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=auto>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/img/favicon.png">
  <link rel="icon" href="/img/favicon.png">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="description" content="Blue~u~u~u">
  <meta name="author" content="Blue~u~u~u">
  <meta name="keywords" content="">
  <meta name="description" content="Mybatis-day04第一章 Mybatis的缓存机制第一节 缓存机制的概述1. 什么是缓存 2. 一级缓存和二级缓存的对比2.1 使用顺序 查询的顺序是：  先查询二级缓存，因为二级缓存中可能会有其他SqlSession已经查出来的数据，可以拿来直接使用。 如果二级缓存没有命中，再查询一级缓存 如果一级缓存也没有命中，则查询数据库 SqlSession关闭之前，一级缓存中的数据会写入二级缓存">
<meta property="og:type" content="article">
<meta property="og:title" content="mybatis-缓存">
<meta property="og:url" content="http://www.slx.blue/2021/12/03/mybatis04/index.html">
<meta property="og:site_name" content="Blue~u~u~u~u">
<meta property="og:description" content="Mybatis-day04第一章 Mybatis的缓存机制第一节 缓存机制的概述1. 什么是缓存 2. 一级缓存和二级缓存的对比2.1 使用顺序 查询的顺序是：  先查询二级缓存，因为二级缓存中可能会有其他SqlSession已经查出来的数据，可以拿来直接使用。 如果二级缓存没有命中，再查询一级缓存 如果一级缓存也没有命中，则查询数据库 SqlSession关闭之前，一级缓存中的数据会写入二级缓存">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_004.png">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_005.png">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_006.png">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_007.png">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_008.png">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_009.png">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_010.png">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_011.png">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_012.png">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_013.png">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_014.png">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_015.png">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_016.png">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_017.png">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_018.png">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_019.png">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_020.png">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_021.png">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_022.png">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_023.png">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_024.png">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_025.png">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_026.png">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_027.png">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_028.png">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_029.png">
<meta property="article:published_time" content="2021-12-03T10:55:46.000Z">
<meta property="article:modified_time" content="2021-12-06T06:38:52.282Z">
<meta property="article:author" content="Blue~u~u~u">
<meta property="article:tag" content="mybatis">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="http://www.slx.blue/2021/12/03/mybatis04/tu_004.png">
  
  <title>mybatis-缓存 - Blue~u~u~u~u</title>

  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4/dist/css/bootstrap.min.css" />


  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@4/github-markdown.min.css" />
  <link  rel="stylesheet" href="/lib/hint/hint.min.css" />

  
    
    
      
      <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@10/styles/github-gist.min.css" />
    
  

  
    <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3/dist/jquery.fancybox.min.css" />
  


<!-- 主题依赖的图标库，不要自行修改 -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_ba1fz6golrf.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_kmeydafke9r.css">


<link  rel="stylesheet" href="/css/main.css" />

<!-- 自定义样式保持在最底部 -->


  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    var CONFIG = {"hostname":"www.slx.blue","root":"/","version":"1.8.12","typing":{"enable":true,"typeSpeed":180,"cursorChar":"_","loop":true},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"right","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"copy_btn":true,"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":true,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":false,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null,"path":"window.location.pathname"}},"search_path":"/local-search.xml"};
  </script>
  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
<meta name="generator" content="Hexo 5.4.0"></head>

<script src="https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/font-awesome/css/font-awesome.min.css"/>
<script src="/live2d-widget/autoload.js"></script>


<body>
  <header style="height: 70vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand" href="/">
      <strong>Blue~u~u</strong>
    </a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                首页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/archives/">
                <i class="iconfont icon-archive-fill"></i>
                归档
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-category-fill"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/links/">
                <i class="iconfont icon-link-fill"></i>
                友链
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
              &nbsp;<i class="iconfont icon-search"></i>&nbsp;
            </a>
          </li>
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

    <div class="banner" id="banner" parallax=true
         style="background: url('/images/default.png') no-repeat center center;
           background-size: cover;">
      <div class="full-bg-img">
        <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
          <div class="page-header text-center fade-in-up">
            <span class="h2" id="subtitle" title="mybatis-缓存">
              
            </span>

            
              <div class="mt-3">
  
  
    <span class="post-meta">
      <i class="iconfont icon-date-fill" aria-hidden="true"></i>
      <time datetime="2021-12-03 18:55" pubdate>
        2021年12月3日 晚上
      </time>
    </span>
  
</div>

<div class="mt-1">
  
    <span class="post-meta mr-2">
      <i class="iconfont icon-chart"></i>
      21k 字
    </span>
  

  
    <span class="post-meta mr-2">
      <i class="iconfont icon-clock-fill"></i>
      
      
      65 分钟
    </span>
  

  
  
    
      <!-- 不蒜子统计文章PV -->
      <span id="busuanzi_container_page_pv" style="display: none">
        <i class="iconfont icon-eye" aria-hidden="true"></i>
        <span id="busuanzi_value_page_pv"></span> 次
      </span>
    
  
</div>

            
          </div>

          
        </div>
      </div>
    </div>
  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div class="py-5" id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">mybatis-缓存</h1>
            
              <p class="note note-info">
                
                  本文最后更新于：6 个月前
                
              </p>
            
            <div class="markdown-body">
              <h1 id="Mybatis-day04"><a href="#Mybatis-day04" class="headerlink" title="Mybatis-day04"></a>Mybatis-day04</h1><h2 id="第一章-Mybatis的缓存机制"><a href="#第一章-Mybatis的缓存机制" class="headerlink" title="第一章 Mybatis的缓存机制"></a>第一章 Mybatis的缓存机制</h2><h3 id="第一节-缓存机制的概述"><a href="#第一节-缓存机制的概述" class="headerlink" title="第一节 缓存机制的概述"></a>第一节 缓存机制的概述</h3><h4 id="1-什么是缓存"><a href="#1-什么是缓存" class="headerlink" title="1. 什么是缓存"></a>1. 什么是缓存</h4><p><img src="http://www.slx.blue/2021/12/03/mybatis04/tu_004.png" srcset="/img/loading.gif" lazyload></p>
<h4 id="2-一级缓存和二级缓存的对比"><a href="#2-一级缓存和二级缓存的对比" class="headerlink" title="2. 一级缓存和二级缓存的对比"></a>2. 一级缓存和二级缓存的对比</h4><h5 id="2-1-使用顺序"><a href="#2-1-使用顺序" class="headerlink" title="2.1 使用顺序"></a>2.1 使用顺序</h5><p><img src="http://www.slx.blue/2021/12/03/mybatis04/tu_005.png" srcset="/img/loading.gif" lazyload></p>
<p>查询的顺序是：</p>
<ul>
<li>先查询二级缓存，因为二级缓存中可能会有其他SqlSession已经查出来的数据，可以拿来直接使用。</li>
<li>如果二级缓存没有命中，再查询一级缓存</li>
<li>如果一级缓存也没有命中，则查询数据库</li>
<li>SqlSession关闭之前，一级缓存中的数据会写入二级缓存</li>
</ul>
<h5 id="2-2-作用范围"><a href="#2-2-作用范围" class="headerlink" title="2.2 作用范围"></a>2.2 作用范围</h5><ul>
<li>一级缓存：SqlSession级别</li>
<li>二级缓存：SqlSessionFactory级别</li>
</ul>
<p><img src="http://www.slx.blue/2021/12/03/mybatis04/tu_006.png" srcset="/img/loading.gif" lazyload></p>
<p> 它们之间范围的大小参考下面图： </p>
<p><img src="http://www.slx.blue/2021/12/03/mybatis04/tu_007.png" srcset="/img/loading.gif" lazyload></p>
<h3 id="第二节-一级缓存"><a href="#第二节-一级缓存" class="headerlink" title="第二节 一级缓存"></a>第二节 一级缓存</h3><h4 id="1-代码验证一级缓存"><a href="#1-代码验证一级缓存" class="headerlink" title="1 代码验证一级缓存"></a>1 代码验证一级缓存</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Test</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testFirstLevelCache</span><span class="hljs-params">()</span></span>&#123;<br>    <span class="hljs-comment">//验证一级缓存的存在:要求两次查询使用的是同一个sqlSession对象</span><br>    <span class="hljs-comment">//一级缓存是Mybatis自动开启的，不需要配置，也无法关闭(表示你必须使用一级缓存)</span><br>    SqlSession sqlSession = sessionFactory.openSession();<br>    EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);<br><br>    Employee employee1 = employeeMapper.selectEmployee(<span class="hljs-number">7</span>);<br>    System.out.println(employee1);<br>    <span class="hljs-comment">//一级缓存什么时候会被清除呢?</span><br>    <span class="hljs-comment">//1. sqlSession提交事务   2. sqlSession调用clearCache()方法</span><br>    <span class="hljs-comment">//3. sqlSession被销毁了close()一级缓存的内容会被写入到二级缓存</span><br>    <span class="hljs-comment">//4. 数据发生改变:其实并没有清除一级缓存，而是修改缓存中数据</span><br>    SqlSession sqlSession2 = sessionFactory.openSession();<br>    EmployeeMapper employeeMapper2 = sqlSession2.getMapper(EmployeeMapper.class);<br>    employee1.setEmpName(<span class="hljs-string">&quot;zs&quot;</span>);<br>    employeeMapper2.updateEmployee(employee1);<br>    sqlSession2.commit();<br><br><br>    Employee employee2 = employeeMapper.selectEmployee(<span class="hljs-number">7</span>);<br>    System.out.println(employee2);<br>&#125;<br></code></pre></td></tr></table></figure>

<p>一共只打印了一条SQL语句。 </p>
<h4 id="2-一级缓存失效的情况"><a href="#2-一级缓存失效的情况" class="headerlink" title="2 一级缓存失效的情况"></a>2 一级缓存失效的情况</h4><ul>
<li>不是同一个SqlSession(因为一级缓存只能用在同一个SqlSession中)</li>
<li>同一个SqlSession但是查询条件发生了变化</li>
<li>同一个SqlSession两次查询期间执行了任何一次增删改操作,那么会改变缓存的数据</li>
<li>同一个SqlSession两次查询期间手动清空了缓存: 调用sqlSession的clearCache()方法</li>
<li>同一个SqlSession两次查询期间提交了事务: 调用sqlSession的commit()方法</li>
</ul>
<h3 id="第三节-二级缓存"><a href="#第三节-二级缓存" class="headerlink" title="第三节 二级缓存"></a>第三节 二级缓存</h3><h4 id="1-代码测试二级缓存"><a href="#1-代码测试二级缓存" class="headerlink" title="1 代码测试二级缓存"></a>1 代码测试二级缓存</h4><h5 id="1-1-开启二级缓存功能"><a href="#1-1-开启二级缓存功能" class="headerlink" title="1.1 开启二级缓存功能"></a>1.1 开启二级缓存功能</h5><p>在想要使用二级缓存的Mapper配置文件中加入cache标签</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment">&lt;!-- 加入cache标签启用二级缓存功能 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">cache</span>/&gt;</span><br></code></pre></td></tr></table></figure>

<h5 id="1-2-让实体类支持序列化"><a href="#1-2-让实体类支持序列化" class="headerlink" title="1.2 让实体类支持序列化"></a>1.2 让实体类支持序列化</h5><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Employee</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Serializable</span> </span>&#123;<br>&#125;<br></code></pre></td></tr></table></figure>

<h5 id="1-3-junit测试"><a href="#1-3-junit测试" class="headerlink" title="1.3 junit测试"></a>1.3 junit测试</h5><p>这个功能的测试操作需要将SqlSessionFactory对象设置为成员变量 </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Test</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testSecondCacheLevel</span><span class="hljs-params">()</span></span>&#123;<br>    <span class="hljs-comment">//测试二级缓存的存在:二级缓存是使用在不同的SqlSession中，但是是同一个SqlSessionFactory</span><br>    <span class="hljs-comment">//二级缓存不是Mybatis自动开启的，需要我们手动进行配置</span><br>    <span class="hljs-comment">//1. 在要进行二级缓存的映射配置文件中开启二级缓存(使用&lt;cache/&gt;标签)</span><br>    <span class="hljs-comment">//2. 要进行二级缓存的POJO类需要实现Serializable接口(进行序列化:将对象的数据存储到硬盘中)</span><br>    <span class="hljs-comment">//3. 二级缓存的创建时机(什么时候数据会写入到二级缓存中):sqlSession对象close()的时候</span><br>    SqlSession sqlSession1 = sessionFactory.openSession();<br>    EmployeeMapper employeeMapper1 = sqlSession1.getMapper(EmployeeMapper.class);<br><br>    SqlSession sqlSession2 = sessionFactory.openSession();<br>    EmployeeMapper employeeMapper2 = sqlSession2.getMapper(EmployeeMapper.class);<br><br>    Employee employee1 = employeeMapper1.selectEmployee(<span class="hljs-number">7</span>);<br>    System.out.println(employee1);<br>    <span class="hljs-comment">//sqlSession1关闭，那么sqlSession1查询到的数据就会写入到二级缓存中</span><br>    sqlSession1.close();<br><br>    Employee employee2 = employeeMapper2.selectEmployee(<span class="hljs-number">7</span>);<br>    System.out.println(employee2);<br>    sqlSession2.close();<br>&#125;<br></code></pre></td></tr></table></figure>

<h5 id="1-4-缓存命中率"><a href="#1-4-缓存命中率" class="headerlink" title="1.4 缓存命中率"></a>1.4 缓存命中率</h5><p>日志中打印的Cache Hit Ratio叫做缓存命中率 </p>
<figure class="highlight avrasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs avrasm">Cache Hit Ratio [<span class="hljs-keyword">com</span>.atguigu.mybatis.EmployeeMapper]: <span class="hljs-number">0.0</span>（<span class="hljs-number">0</span>/<span class="hljs-number">1</span>)<br>Cache Hit Ratio [<span class="hljs-keyword">com</span>.atguigu.mybatis.EmployeeMapper]: <span class="hljs-number">0.5</span>（<span class="hljs-number">1</span>/<span class="hljs-number">2</span>）<br>Cache Hit Ratio [<span class="hljs-keyword">com</span>.atguigu.mybatis.EmployeeMapper]: <span class="hljs-number">0.6666666666666666</span>（<span class="hljs-number">2</span>/<span class="hljs-number">3</span>）<br>Cache Hit Ratio [<span class="hljs-keyword">com</span>.atguigu.mybatis.EmployeeMapper]: <span class="hljs-number">0.75</span>（<span class="hljs-number">3</span>/<span class="hljs-number">4</span>）<br>Cache Hit Ratio [<span class="hljs-keyword">com</span>.atguigu.mybatis.EmployeeMapper]: <span class="hljs-number">0.8</span>（<span class="hljs-number">4</span>/<span class="hljs-number">5</span>）<br></code></pre></td></tr></table></figure>

<p>缓存命中率=命中缓存的次数/查询的总次数 </p>
<h4 id="2-查询结果存入二级缓存的时机"><a href="#2-查询结果存入二级缓存的时机" class="headerlink" title="2 查询结果存入二级缓存的时机"></a>2 查询结果存入二级缓存的时机</h4><p>结论：SqlSession关闭的时候，一级缓存中的内容会被存入二级缓存 </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 1.开启两个SqlSession</span><br>SqlSession session01 = factory.openSession();<br>SqlSession session02 = factory.openSession();<br>    <br><span class="hljs-comment">// 2.获取两个EmployeeMapper</span><br>EmployeeMapper employeeMapper01 = session01.getMapper(EmployeeMapper.class);<br>EmployeeMapper employeeMapper02 = session02.getMapper(EmployeeMapper.class);<br>    <br><span class="hljs-comment">// 3.使用两个EmployeeMapper做两次查询，返回两个Employee对象</span><br>Employee employee01 = employeeMapper01.selectEmployeeById(<span class="hljs-number">2</span>);<br>Employee employee02 = employeeMapper02.selectEmployeeById(<span class="hljs-number">2</span>);<br>    <br><span class="hljs-comment">// 4.比较两个Employee对象</span><br>System.out.println(<span class="hljs-string">&quot;employee02.equals(employee01) = &quot;</span> + employee02.equals(employee01));<br></code></pre></td></tr></table></figure>

<p>上面代码打印的结果是： </p>
<figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs routeros"><span class="hljs-builtin-name">DEBUG</span> 12-01 10:10:32,209 Cache Hit Ratio [com.atguigu.mybatis.EmployeeMapper]: 0.0  (LoggingCache.java:62) <br><span class="hljs-builtin-name">DEBUG</span> 12-01 10:10:32,570 ==&gt;  Preparing: select emp_id,emp_name,emp_salary,emp_gender,emp_age <span class="hljs-keyword">from</span> t_emp where <span class="hljs-attribute">emp_id</span>=?   (BaseJdbcLogger.java:145) <br><span class="hljs-builtin-name">DEBUG</span> 12-01 10:10:32,624 ==&gt; Parameters: 2(Integer)  (BaseJdbcLogger.java:145) <br><span class="hljs-builtin-name">DEBUG</span> 12-01 10:10:32,643 &lt;==      Total: 1  (BaseJdbcLogger.java:145) <br><span class="hljs-builtin-name">DEBUG</span> 12-01 10:10:32,644 Cache Hit Ratio [com.atguigu.mybatis.EmployeeMapper]: 0.0  (LoggingCache.java:62) <br><span class="hljs-builtin-name">DEBUG</span> 12-01 10:10:32,661 ==&gt;  Preparing: select emp_id,emp_name,emp_salary,emp_gender,emp_age <span class="hljs-keyword">from</span> t_emp where <span class="hljs-attribute">emp_id</span>=?   (BaseJdbcLogger.java:145) <br><span class="hljs-builtin-name">DEBUG</span> 12-01 10:10:32,662 ==&gt; Parameters: 2(Integer)  (BaseJdbcLogger.java:145) <br><span class="hljs-builtin-name">DEBUG</span> 12-01 10:10:32,665 &lt;==      Total: 1  (BaseJdbcLogger.java:145) <br>employee02.equals(employee01) = <span class="hljs-literal">false</span><br></code></pre></td></tr></table></figure>

<p>修改代码： </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 1.开启两个SqlSession</span><br>SqlSession session01 = factory.openSession();<br>SqlSession session02 = factory.openSession();<br>    <br><span class="hljs-comment">// 2.获取两个EmployeeMapper</span><br>EmployeeMapper employeeMapper01 = session01.getMapper(EmployeeMapper.class);<br>EmployeeMapper employeeMapper02 = session02.getMapper(EmployeeMapper.class);<br>    <br><span class="hljs-comment">// 3.使用两个EmployeeMapper做两次查询，返回两个Employee对象</span><br>Employee employee01 = employeeMapper01.selectEmployeeById(<span class="hljs-number">2</span>);<br>    <br><span class="hljs-comment">// ※第一次查询完成后，把所在的SqlSession关闭，使一级缓存中的数据存入二级缓存</span><br>session01.close();<br>Employee employee02 = employeeMapper02.selectEmployeeById(<span class="hljs-number">2</span>);<br>    <br><span class="hljs-comment">// 4.比较两个Employee对象</span><br>System.out.println(<span class="hljs-string">&quot;employee02.equals(employee01) = &quot;</span> + employee02.equals(employee01));<br>    <br><span class="hljs-comment">// 5.另外一个SqlSession用完正常关闭</span><br>session02.close();<br></code></pre></td></tr></table></figure>

<p> 打印结果： </p>
<figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs routeros"><span class="hljs-builtin-name">DEBUG</span> 12-01 10:14:06,804 Cache Hit Ratio [com.atguigu.mybatis.EmployeeMapper]: 0.0  (LoggingCache.java:62) <br><span class="hljs-builtin-name">DEBUG</span> 12-01 10:14:07,135 ==&gt;  Preparing: select emp_id,emp_name,emp_salary,emp_gender,emp_age <span class="hljs-keyword">from</span> t_emp where <span class="hljs-attribute">emp_id</span>=?   (BaseJdbcLogger.java:145) <br><span class="hljs-builtin-name">DEBUG</span> 12-01 10:14:07,202 ==&gt; Parameters: 2(Integer)  (BaseJdbcLogger.java:145) <br><span class="hljs-builtin-name">DEBUG</span> 12-01 10:14:07,224 &lt;==      Total: 1  (BaseJdbcLogger.java:145) <br><span class="hljs-builtin-name">DEBUG</span> 12-01 10:14:07,308 Cache Hit Ratio [com.atguigu.mybatis.EmployeeMapper]: 0.5  (LoggingCache.java:62) <br>employee02.equals(employee01) = <span class="hljs-literal">false</span><br></code></pre></td></tr></table></figure>

<h4 id="3-二级缓存相关配置-了解"><a href="#3-二级缓存相关配置-了解" class="headerlink" title="3 二级缓存相关配置(了解)"></a>3 二级缓存相关配置(了解)</h4><p>在Mapper配置文件中添加的cache标签可以设置一些属性：</p>
<ul>
<li><p>eviction属性：缓存回收策略</p>
<p>LRU（Least Recently Used） – 最近最少使用的：移除最长时间不被使用的对象。</p>
<p>FIFO（First in First out） – 先进先出：按对象进入缓存的顺序来移除它们。</p>
<p>SOFT – 软引用：移除基于垃圾回收器状态和软引用规则的对象。</p>
<p>WEAK – 弱引用：更积极地移除基于垃圾收集器状态和弱引用规则的对象。</p>
<p>默认的是 LRU。</p>
</li>
<li><p>flushInterval属性：刷新间隔，单位毫秒</p>
<p>默认情况是不设置，也就是没有刷新间隔，缓存仅仅调用语句时刷新</p>
</li>
<li><p>size属性：引用数目，正整数</p>
<p>代表缓存最多可以存储多少个对象，太大容易导致内存溢出</p>
</li>
<li><p>readOnly属性：只读，true/false</p>
<p>true：只读缓存；会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。</p>
<p>false：读写缓存；会返回缓存对象的拷贝（通过序列化）。这会慢一些，但是安全，因此默认是 false。</p>
</li>
</ul>
<h3 id="第四节-整合EHCache"><a href="#第四节-整合EHCache" class="headerlink" title="第四节 整合EHCache"></a>第四节 整合EHCache</h3><h4 id="1-EHCache简介"><a href="#1-EHCache简介" class="headerlink" title="1. EHCache简介"></a>1. EHCache简介</h4><p>Ehcache 是一种开源的、基于标准的缓存，可提高性能、卸载数据库并简化可扩展性。它是最广泛使用的基于 Java 的缓存，因为它健壮、经过验证、功能齐全，并且与其他流行的库和框架集成。 Ehcache 从进程内缓存一直扩展到具有 TB 级缓存的混合进程内/进程外部署。  官网地址为:  <a target="_blank" rel="noopener" href="https://www.ehcache.org/">https://www.ehcache.org/</a> </p>
<h4 id="2-Mybatis整合操作"><a href="#2-Mybatis整合操作" class="headerlink" title="2. Mybatis整合操作"></a>2. Mybatis整合操作</h4><h5 id="2-1-添加依赖"><a href="#2-1-添加依赖" class="headerlink" title="2.1 添加依赖"></a>2.1 添加依赖</h5><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment">&lt;!-- Mybatis EHCache整合包 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.mybatis.caches<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>mybatis-ehcache<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.2.1<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-comment">&lt;!-- slf4j日志门面的一个具体实现 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>ch.qos.logback<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>logback-classic<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.2.3<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h5 id="2-2-创建EHCache配置文件"><a href="#2-2-创建EHCache配置文件" class="headerlink" title="2.2 创建EHCache配置文件"></a>2.2 创建EHCache配置文件</h5><p>ehcache.xml</p>
<p><img src="http://www.slx.blue/2021/12/03/mybatis04/tu_008.png" srcset="/img/loading.gif" lazyload></p>
<p>文件内容</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-meta">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">ehcache</span> <span class="hljs-attr">xmlns:xsi</span>=<span class="hljs-string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span><br><span class="hljs-tag">         <span class="hljs-attr">xsi:noNamespaceSchemaLocation</span>=<span class="hljs-string">&quot;http://ehcache.org/ehcache.xsd&quot;</span>&gt;</span><br>    <span class="hljs-comment">&lt;!-- 磁盘保存路径 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">diskStore</span> <span class="hljs-attr">path</span>=<span class="hljs-string">&quot;D:\atguigu\ehcache&quot;</span>/&gt;</span><br>    <span class="hljs-comment">&lt;!--</span><br><span class="hljs-comment">    maxElementsInMemory:设置 在内存中缓存 对象的个数</span><br><span class="hljs-comment">    maxElementsOnDisk：设置 在硬盘中缓存 对象的个数</span><br><span class="hljs-comment">    eternal：设置缓存是否 永远不过期</span><br><span class="hljs-comment">    overflowToDisk：当系统宕机的时候是否保存到磁盘上</span><br><span class="hljs-comment">    maxElementsInMemory的时候，是否转移到硬盘中</span><br><span class="hljs-comment">    timeToIdleSeconds：当2次访问 超过该值的时候，将缓存对象失效</span><br><span class="hljs-comment">    timeToLiveSeconds：一个缓存对象 最多存放的时间（生命周期）</span><br><span class="hljs-comment">    diskExpiryThreadIntervalSeconds：设置每隔多长时间，通过一个线程来清理硬盘中的缓存</span><br><span class="hljs-comment">    clearOnFlush: 内存数量最大时是否清除</span><br><span class="hljs-comment">    memoryStoreEvictionPolicy：当超过缓存对象的最大值时，处理的策略；LRU (最少使用)，FIFO (先进先出), LFU (最少访问次数)</span><br><span class="hljs-comment">    --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">defaultCache</span></span><br><span class="hljs-tag">                  <span class="hljs-attr">maxElementsInMemory</span>=<span class="hljs-string">&quot;1000&quot;</span></span><br><span class="hljs-tag">                  <span class="hljs-attr">maxElementsOnDisk</span>=<span class="hljs-string">&quot;10000000&quot;</span></span><br><span class="hljs-tag">                  <span class="hljs-attr">eternal</span>=<span class="hljs-string">&quot;false&quot;</span></span><br><span class="hljs-tag">                  <span class="hljs-attr">overflowToDisk</span>=<span class="hljs-string">&quot;true&quot;</span></span><br><span class="hljs-tag">                  <span class="hljs-attr">timeToIdleSeconds</span>=<span class="hljs-string">&quot;120&quot;</span></span><br><span class="hljs-tag">                  <span class="hljs-attr">timeToLiveSeconds</span>=<span class="hljs-string">&quot;120&quot;</span></span><br><span class="hljs-tag">                  <span class="hljs-attr">diskExpiryThreadIntervalSeconds</span>=<span class="hljs-string">&quot;120&quot;</span></span><br><span class="hljs-tag">                  <span class="hljs-attr">memoryStoreEvictionPolicy</span>=<span class="hljs-string">&quot;LRU&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">defaultCache</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">ehcache</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>引入第三方框架或工具时，配置文件的文件名可以自定义吗？</p>
<ul>
<li>可以自定义：文件名是由我告诉其他环境</li>
<li>不能自定义：文件名是框架内置的、约定好的，就不能自定义，以避免框架无法加载这个文件</li>
</ul>
<h5 id="2-3-指定缓存管理器的具体类型"><a href="#2-3-指定缓存管理器的具体类型" class="headerlink" title="2.3 指定缓存管理器的具体类型"></a>2.3 指定缓存管理器的具体类型</h5><p>还是到查询操作所的Mapper配置文件中，找到之前设置的cache标签： </p>
<p><img src="http://www.slx.blue/2021/12/03/mybatis04/tu_009.png" srcset="/img/loading.gif" lazyload></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">cache</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;org.mybatis.caches.ehcache.EhcacheCache&quot;</span>/&gt;</span><br></code></pre></td></tr></table></figure>

<h5 id="2-4-加入logback日志"><a href="#2-4-加入logback日志" class="headerlink" title="2.4 加入logback日志"></a>2.4 加入logback日志</h5><p>存在SLF4J时，作为简易日志的log4j将失效，此时我们需要借助SLF4J的具体实现logback来打印日志。 </p>
<h6 id="2-4-1-各种Java日志框架简介"><a href="#2-4-1-各种Java日志框架简介" class="headerlink" title="2.4.1 各种Java日志框架简介"></a>2.4.1 各种Java日志框架简介</h6><p>门面：</p>
<table>
<thead>
<tr>
<th>名称</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>JCL（Jakarta Commons Logging）</td>
<td>陈旧</td>
</tr>
<tr>
<td>SLF4J（Simple Logging Facade for Java）★</td>
<td>适合</td>
</tr>
<tr>
<td>jboss-logging</td>
<td>特殊专业领域使用</td>
</tr>
</tbody></table>
<p>实现：</p>
<table>
<thead>
<tr>
<th>名称</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>log4j★</td>
<td>最初版</td>
</tr>
<tr>
<td>JUL（java.util.logging）</td>
<td>JDK自带</td>
</tr>
<tr>
<td>log4j2</td>
<td>Apache收购log4j后全面重构，内部实现和log4j完全不同</td>
</tr>
<tr>
<td>logback★</td>
<td>优雅、强大</td>
</tr>
</tbody></table>
<p>注：标记★的技术是同一作者。</p>
<h6 id="2-4-2-logback配置文件"><a href="#2-4-2-logback配置文件" class="headerlink" title="2.4.2 logback配置文件"></a>2.4.2 logback配置文件</h6><p><img src="http://www.slx.blue/2021/12/03/mybatis04/tu_010.png" srcset="/img/loading.gif" lazyload></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-meta">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">configuration</span> <span class="hljs-attr">debug</span>=<span class="hljs-string">&quot;true&quot;</span>&gt;</span><br>    <span class="hljs-comment">&lt;!-- 指定日志输出的位置 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">appender</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;STDOUT&quot;</span></span><br><span class="hljs-tag">        <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;ch.qos.logback.core.ConsoleAppender&quot;</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">encoder</span>&gt;</span><br>            <span class="hljs-comment">&lt;!-- 日志输出的格式 --&gt;</span><br>            <span class="hljs-comment">&lt;!-- 按照顺序分别是：时间、日志级别、线程名称、打印日志的类、日志主体内容、换行 --&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">pattern</span>&gt;</span>[%d&#123;HH:mm:ss.SSS&#125;] [%-5level] [%thread] [%logger] [%msg]%n<span class="hljs-tag">&lt;/<span class="hljs-name">pattern</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">encoder</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">appender</span>&gt;</span><br>    <br>    <span class="hljs-comment">&lt;!-- 设置全局日志级别。日志级别按顺序分别是：DEBUG、INFO、WARN、ERROR --&gt;</span><br>    <span class="hljs-comment">&lt;!-- 指定任何一个日志级别都只打印当前级别和后面级别的日志。 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">root</span> <span class="hljs-attr">level</span>=<span class="hljs-string">&quot;DEBUG&quot;</span>&gt;</span><br>        <span class="hljs-comment">&lt;!-- 指定打印日志的appender，这里通过“STDOUT”引用了前面配置的appender --&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">appender-ref</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">&quot;STDOUT&quot;</span> /&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">root</span>&gt;</span><br>    <br>    <span class="hljs-comment">&lt;!-- 根据特殊需求指定局部日志级别 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">logger</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;com.atguigu.crowd.mapper&quot;</span> <span class="hljs-attr">level</span>=<span class="hljs-string">&quot;DEBUG&quot;</span>/&gt;</span><br>    <br><span class="hljs-tag">&lt;/<span class="hljs-name">configuration</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h6 id="2-4-3-junit测试"><a href="#2-4-3-junit测试" class="headerlink" title="2.4.3 junit测试"></a>2.4.3 junit测试</h6><p>正常按照二级缓存的方式测试即可。因为整合EHCache后，其实就是使用EHCache代替了Mybatis自带的二级缓存。 </p>
<h6 id="2-4-4-EHCache配置文件说明"><a href="#2-4-4-EHCache配置文件说明" class="headerlink" title="2.4.4 EHCache配置文件说明"></a>2.4.4 EHCache配置文件说明</h6><p>当借助CacheManager.add(“缓存名称”)创建Cache时，EhCache便会采用<defalutCache>指定的的管理策略。</defalutCache></p>
<p>defaultCache标签各属性说明：</p>
<table>
<thead>
<tr>
<th>属性名</th>
<th>是否必须</th>
<th>作用</th>
</tr>
</thead>
<tbody><tr>
<td>maxElementsInMemory</td>
<td>是</td>
<td>在内存中缓存的element的最大数目</td>
</tr>
<tr>
<td>maxElementsOnDisk</td>
<td>是</td>
<td>在磁盘上缓存的element的最大数目，若是0表示无穷大</td>
</tr>
<tr>
<td>eternal</td>
<td>是</td>
<td>设定缓存的elements是否永远不过期。 如果为true，则缓存的数据始终有效， 如果为false那么还要根据timeToIdleSeconds、timeToLiveSeconds判断</td>
</tr>
<tr>
<td>overflowToDisk</td>
<td>是</td>
<td>设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上</td>
</tr>
<tr>
<td>timeToIdleSeconds</td>
<td>否</td>
<td>当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时， 这些数据便会删除，默认值是0,也就是可闲置时间无穷大</td>
</tr>
<tr>
<td>timeToLiveSeconds</td>
<td>否</td>
<td>缓存element的有效生命期，默认是0.,也就是element存活时间无穷大</td>
</tr>
<tr>
<td>diskSpoolBufferSizeMB</td>
<td>否</td>
<td>DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区</td>
</tr>
<tr>
<td>diskPersistent</td>
<td>否</td>
<td>在VM重启的时候是否启用磁盘保存EhCache中的数据，默认是false。</td>
</tr>
<tr>
<td>diskExpiryThreadIntervalSeconds</td>
<td>否</td>
<td>磁盘缓存的清理线程运行间隔，默认是120秒。每个120s， 相应的线程会进行一次EhCache中数据的清理工作</td>
</tr>
<tr>
<td>memoryStoreEvictionPolicy</td>
<td>否</td>
<td>当内存缓存达到最大，有新的element加入的时候， 移除缓存中element的策略。 默认是LRU（最近最少使用），可选的有LFU（最不常使用）和FIFO（先进先出）</td>
</tr>
</tbody></table>
<h3 id="第五节-缓存的原理"><a href="#第五节-缓存的原理" class="headerlink" title="第五节 缓存的原理"></a>第五节 缓存的原理</h3><h4 id="1-Cache接口"><a href="#1-Cache接口" class="headerlink" title="1. Cache接口"></a>1. Cache接口</h4><h5 id="1-1-Cache接口的重要地位"><a href="#1-1-Cache接口的重要地位" class="headerlink" title="1.1 Cache接口的重要地位"></a>1.1 Cache接口的重要地位</h5><p>org.apache.ibatis.cache.Cache接口：所有缓存都必须实现的顶级接口</p>
<p><img src="http://www.slx.blue/2021/12/03/mybatis04/tu_011.png" srcset="/img/loading.gif" lazyload></p>
<h5 id="1-2-Cache接口中的方法"><a href="#1-2-Cache接口中的方法" class="headerlink" title="1.2 Cache接口中的方法"></a>1.2 Cache接口中的方法</h5><p><img src="http://www.slx.blue/2021/12/03/mybatis04/tu_012.png" srcset="/img/loading.gif" lazyload></p>
<table>
<thead>
<tr>
<th>方法名</th>
<th>作用</th>
</tr>
</thead>
<tbody><tr>
<td>putObject()</td>
<td>将对象存入缓存</td>
</tr>
<tr>
<td>getObject()</td>
<td>从缓存中取出对象</td>
</tr>
<tr>
<td>removeObject()</td>
<td>从缓存中删除对象</td>
</tr>
</tbody></table>
<h5 id="1-3-缓存的本质"><a href="#1-3-缓存的本质" class="headerlink" title="1.3 缓存的本质"></a>1.3 缓存的本质</h5><p>根据Cache接口中方法的声明我们能够看到，缓存的本质是一个<strong>Map</strong>。 </p>
<h4 id="2-PerpetualCache类"><a href="#2-PerpetualCache类" class="headerlink" title="2. PerpetualCache类"></a>2. PerpetualCache类</h4><p><img src="http://www.slx.blue/2021/12/03/mybatis04/tu_013.png" srcset="/img/loading.gif" lazyload></p>
<p>org.apache.ibatis.cache.impl.PerpetualCache是Mybatis的默认缓存，也是Cache接口的默认实现。Mybatis一级缓存和自带的二级缓存都是通过PerpetualCache来操作缓存数据的。但是这就奇怪了，同样是PerpetualCache这个类，怎么能区分出来两种不同级别的缓存呢？</p>
<p>其实很简单，调用者不同。</p>
<ul>
<li>一级缓存：由BaseExecutor调用PerpetualCache</li>
<li>二级缓存：由CachingExecutor调用PerpetualCache，而CachingExecutor可以看做是对BaseExecutor的装饰</li>
</ul>
<h4 id="3-一级缓存机制"><a href="#3-一级缓存机制" class="headerlink" title="3. 一级缓存机制"></a>3. 一级缓存机制</h4><p><img src="http://www.slx.blue/2021/12/03/mybatis04/tu_014.png" srcset="/img/loading.gif" lazyload></p>
<p> org.apache.ibatis.executor.BaseExecutor类中的关键方法： </p>
<h5 id="3-1-query-方法"><a href="#3-1-query-方法" class="headerlink" title="3.1 query()方法"></a>3.1 query()方法</h5><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> &lt;E&gt; <span class="hljs-function">List&lt;E&gt; <span class="hljs-title">query</span><span class="hljs-params">(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)</span> <span class="hljs-keyword">throws</span> SQLException </span>&#123;<br>    ErrorContext.instance().resource(ms.getResource()).activity(<span class="hljs-string">&quot;executing a query&quot;</span>).object(ms.getId());<br>    <span class="hljs-keyword">if</span> (closed) &#123;<br>        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ExecutorException(<span class="hljs-string">&quot;Executor was closed.&quot;</span>);<br>    &#125;<br>    <span class="hljs-keyword">if</span> (queryStack == <span class="hljs-number">0</span> &amp;&amp; ms.isFlushCacheRequired()) &#123;<br>        clearLocalCache();<br>    &#125;<br>    List&lt;E&gt; list;<br>    <span class="hljs-keyword">try</span> &#123;<br>        queryStack++;<br>        <br>        <span class="hljs-comment">// 尝试从本地缓存中获取数据</span><br>        list = resultHandler == <span class="hljs-keyword">null</span> ? (List&lt;E&gt;) localCache.getObject(key) : <span class="hljs-keyword">null</span>;<br>        <br>        <span class="hljs-keyword">if</span> (list != <span class="hljs-keyword">null</span>) &#123;<br>            handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);<br>        &#125; <span class="hljs-keyword">else</span> &#123;<br>            <br>            <span class="hljs-comment">// 如果本地缓存中没有查询到数据，则查询数据库</span><br>            list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);<br>        &#125;<br>    &#125; <span class="hljs-keyword">finally</span> &#123;<br>        queryStack--;<br>    &#125;<br>    <span class="hljs-keyword">if</span> (queryStack == <span class="hljs-number">0</span>) &#123;<br>        <span class="hljs-keyword">for</span> (org.apache.ibatis.executor.BaseExecutor.DeferredLoad deferredLoad : deferredLoads) &#123;<br>            deferredLoad.load();<br>        &#125;<br>        <span class="hljs-comment">// issue #601</span><br>        deferredLoads.clear();<br>        <span class="hljs-keyword">if</span> (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) &#123;<br>            <span class="hljs-comment">// issue #482</span><br>            clearLocalCache();<br>        &#125;<br>    &#125;<br>    <span class="hljs-keyword">return</span> list;<br>&#125;<br></code></pre></td></tr></table></figure>

<h5 id="3-2-queryFromDatabase-方法"><a href="#3-2-queryFromDatabase-方法" class="headerlink" title="3.2 queryFromDatabase()方法"></a>3.2 queryFromDatabase()方法</h5><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">private</span> &lt;E&gt; <span class="hljs-function">List&lt;E&gt; <span class="hljs-title">queryFromDatabase</span><span class="hljs-params">(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)</span> <span class="hljs-keyword">throws</span> SQLException </span>&#123;<br>    List&lt;E&gt; list;<br>    localCache.putObject(key, EXECUTION_PLACEHOLDER);<br>    <span class="hljs-keyword">try</span> &#123;<br>        <br>        <span class="hljs-comment">// 从数据库中查询数据</span><br>        list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);<br>    &#125; <span class="hljs-keyword">finally</span> &#123;<br>        localCache.removeObject(key);<br>    &#125;<br>    <br>    <span class="hljs-comment">// 将数据存入本地缓存</span><br>    localCache.putObject(key, list);<br>    <span class="hljs-keyword">if</span> (ms.getStatementType() == StatementType.CALLABLE) &#123;<br>        localOutputParameterCache.putObject(key, parameter);<br>    &#125;<br>    <span class="hljs-keyword">return</span> list;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="4-二级缓存机制"><a href="#4-二级缓存机制" class="headerlink" title="4. 二级缓存机制"></a>4. 二级缓存机制</h4><p><img src="http://www.slx.blue/2021/12/03/mybatis04/tu_015.png" srcset="/img/loading.gif" lazyload></p>
<p>下面我们来看看CachingExecutor类中的query()方法在不同情况下使用的具体缓存对象： </p>
<h5 id="4-1-未开启二级缓存"><a href="#4-1-未开启二级缓存" class="headerlink" title="4.1 未开启二级缓存"></a>4.1 未开启二级缓存</h5><p><img src="http://www.slx.blue/2021/12/03/mybatis04/tu_016.png" srcset="/img/loading.gif" lazyload></p>
<h5 id="4-1-使用Mybatis自带的二级缓存"><a href="#4-1-使用Mybatis自带的二级缓存" class="headerlink" title="4.1 使用Mybatis自带的二级缓存"></a>4.1 使用Mybatis自带的二级缓存</h5><p><img src="http://www.slx.blue/2021/12/03/mybatis04/tu_017.png" srcset="/img/loading.gif" lazyload></p>
<h5 id="4-1-使用EHCache"><a href="#4-1-使用EHCache" class="headerlink" title="4.1 使用EHCache"></a>4.1 使用EHCache</h5><p><img src="http://www.slx.blue/2021/12/03/mybatis04/tu_018.png" srcset="/img/loading.gif" lazyload></p>
<h2 id="第二章-逆向工程"><a href="#第二章-逆向工程" class="headerlink" title="第二章 逆向工程"></a>第二章 逆向工程</h2><h3 id="第一节-概念"><a href="#第一节-概念" class="headerlink" title="第一节 概念"></a>第一节 概念</h3><ul>
<li>正向工程：先创建Java实体类，由框架负责根据实体类生成数据库表。Hibernate是支持正向工程的。</li>
<li>逆向工程：先创建数据库表，由框架负责根据数据库表，反向生成如下资源：<ul>
<li>Java实体类</li>
<li>Mapper接口</li>
<li>Mapper配置文件</li>
</ul>
</li>
</ul>
<h3 id="第二节-基本原理"><a href="#第二节-基本原理" class="headerlink" title="第二节 基本原理"></a>第二节 基本原理</h3><p><img src="http://www.slx.blue/2021/12/03/mybatis04/tu_019.png" srcset="/img/loading.gif" lazyload></p>
<h3 id="第三节-逆向工程的具体操作"><a href="#第三节-逆向工程的具体操作" class="headerlink" title="第三节 逆向工程的具体操作"></a>第三节 逆向工程的具体操作</h3><h4 id="1-配置POM"><a href="#1-配置POM" class="headerlink" title="1. 配置POM"></a>1. 配置POM</h4><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment">&lt;!-- 依赖MyBatis核心包 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.mybatis<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>mybatis<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>3.5.7<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>    <span class="hljs-comment">&lt;!--mysql驱动--&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>mysql<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>mysql-connector-java<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>5.1.3<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>runtime<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>    <span class="hljs-comment">&lt;!--log4j--&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>log4j<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>log4j<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.2.17<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>    <span class="hljs-comment">&lt;!--junit--&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>junit<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>junit<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>4.12<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>test<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>    <span class="hljs-comment">&lt;!--lombok--&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.projectlombok<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>lombok<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.18.8<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>provided<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span><br><br><span class="hljs-comment">&lt;!-- 控制Maven在构建过程中相关配置 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">build</span>&gt;</span><br><br>    <span class="hljs-comment">&lt;!-- 构建过程中用到的插件 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">plugins</span>&gt;</span><br><br>        <span class="hljs-comment">&lt;!-- 具体插件，逆向工程的操作是以构建过程中插件形式出现的 --&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">plugin</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.mybatis.generator<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>mybatis-generator-maven-plugin<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.3.0<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br><br>            <span class="hljs-comment">&lt;!-- 插件的依赖 --&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span><br><br>                <span class="hljs-comment">&lt;!-- 逆向工程的核心依赖 --&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>                    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.mybatis.generator<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>                    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>mybatis-generator-core<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>                    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.3.2<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>                <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><br>                <span class="hljs-comment">&lt;!-- 数据库连接池 --&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>                    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.mchange<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>                    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>c3p0<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>                    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>0.9.2<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>                <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><br>                <span class="hljs-comment">&lt;!-- MySQL驱动 --&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>                    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>mysql<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>                    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>mysql-connector-java<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>                    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>5.1.8<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>                <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">plugin</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">plugins</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">build</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h4 id="2-MBG配置文件"><a href="#2-MBG配置文件" class="headerlink" title="2. MBG配置文件"></a>2. MBG配置文件</h4><p>文件名必须是:generatorConfig.xml</p>
<p><img src="http://www.slx.blue/2021/12/03/mybatis04/tu_020.png" srcset="/img/loading.gif" lazyload></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-meta">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span><br><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">generatorConfiguration</span></span><br><span class="hljs-meta">        <span class="hljs-meta-keyword">PUBLIC</span> <span class="hljs-meta-string">&quot;-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN&quot;</span></span><br><span class="hljs-meta">        <span class="hljs-meta-string">&quot;http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd&quot;</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">generatorConfiguration</span>&gt;</span><br>    <span class="hljs-comment">&lt;!--</span><br><span class="hljs-comment">            targetRuntime: 执行生成的逆向工程的版本</span><br><span class="hljs-comment">                    MyBatis3Simple: 生成基本的CRUD（清新简洁版）</span><br><span class="hljs-comment">                    MyBatis3: 生成带条件的CRUD（奢华尊享版）</span><br><span class="hljs-comment">     --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">context</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;DB2Tables&quot;</span> <span class="hljs-attr">targetRuntime</span>=<span class="hljs-string">&quot;MyBatis3&quot;</span>&gt;</span><br>        <span class="hljs-comment">&lt;!-- 数据库的连接信息 --&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">jdbcConnection</span> <span class="hljs-attr">driverClass</span>=<span class="hljs-string">&quot;com.mysql.jdbc.Driver&quot;</span></span><br><span class="hljs-tag">                        <span class="hljs-attr">connectionURL</span>=<span class="hljs-string">&quot;jdbc:mysql://localhost:3306/mybatis-example&quot;</span></span><br><span class="hljs-tag">                        <span class="hljs-attr">userId</span>=<span class="hljs-string">&quot;root&quot;</span></span><br><span class="hljs-tag">                        <span class="hljs-attr">password</span>=<span class="hljs-string">&quot;123456&quot;</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">jdbcConnection</span>&gt;</span><br>        <span class="hljs-comment">&lt;!--</span><br><span class="hljs-comment">            javaBean的生成策略</span><br><span class="hljs-comment">            targetPackage 表示生成的JavaBean存放到哪个包中</span><br><span class="hljs-comment">            targetProject 表示生成的JavaBean存放到哪个主目录中</span><br><span class="hljs-comment">        --&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">javaModelGenerator</span> <span class="hljs-attr">targetPackage</span>=<span class="hljs-string">&quot;com.atguigu.pojo&quot;</span> <span class="hljs-attr">targetProject</span>=<span class="hljs-string">&quot;.\src\main\java&quot;</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;enableSubPackages&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;true&quot;</span> /&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;trimStrings&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;true&quot;</span> /&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">javaModelGenerator</span>&gt;</span><br>        <span class="hljs-comment">&lt;!--</span><br><span class="hljs-comment">            SQL映射文件的生成策略</span><br><span class="hljs-comment">         --&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">sqlMapGenerator</span> <span class="hljs-attr">targetPackage</span>=<span class="hljs-string">&quot;com.atguigu.mapper&quot;</span>  <span class="hljs-attr">targetProject</span>=<span class="hljs-string">&quot;.\src\main\resources&quot;</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;enableSubPackages&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;true&quot;</span> /&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">sqlMapGenerator</span>&gt;</span><br>        <span class="hljs-comment">&lt;!-- Mapper接口的生成策略 --&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">javaClientGenerator</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;XMLMAPPER&quot;</span> <span class="hljs-attr">targetPackage</span>=<span class="hljs-string">&quot;com.atguigu.mapper&quot;</span>  <span class="hljs-attr">targetProject</span>=<span class="hljs-string">&quot;.\src\main\java&quot;</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;enableSubPackages&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;true&quot;</span> /&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">javaClientGenerator</span>&gt;</span><br>        <span class="hljs-comment">&lt;!-- 逆向分析的表 --&gt;</span><br>        <span class="hljs-comment">&lt;!-- tableName设置为*号，可以对应所有表，此时不写domainObjectName --&gt;</span><br>        <span class="hljs-comment">&lt;!-- domainObjectName属性指定生成出来的实体类的类名 --&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">table</span> <span class="hljs-attr">tableName</span>=<span class="hljs-string">&quot;t_emp&quot;</span> <span class="hljs-attr">domainObjectName</span>=<span class="hljs-string">&quot;Employee&quot;</span>/&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">table</span> <span class="hljs-attr">tableName</span>=<span class="hljs-string">&quot;t_customer&quot;</span> <span class="hljs-attr">domainObjectName</span>=<span class="hljs-string">&quot;Customer&quot;</span>/&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">table</span> <span class="hljs-attr">tableName</span>=<span class="hljs-string">&quot;t_order&quot;</span> <span class="hljs-attr">domainObjectName</span>=<span class="hljs-string">&quot;Order&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">context</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">generatorConfiguration</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h4 id="3-执行MBG插件的generate目标"><a href="#3-执行MBG插件的generate目标" class="headerlink" title="3. 执行MBG插件的generate目标"></a>3. 执行MBG插件的generate目标</h4><p><img src="http://www.slx.blue/2021/12/03/mybatis04/tu_021.png" srcset="/img/loading.gif" lazyload></p>
<h4 id="4-效果"><a href="#4-效果" class="headerlink" title="4. 效果"></a>4. 效果</h4><p><img src="http://www.slx.blue/2021/12/03/mybatis04/tu_022.png" srcset="/img/loading.gif" lazyload></p>
<h4 id="5-测试代码"><a href="#5-测试代码" class="headerlink" title="5. 测试代码"></a>5. 测试代码</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.atguigu;<br><br><span class="hljs-keyword">import</span> com.atguigu.mapper.EmployeeMapper;<br><span class="hljs-keyword">import</span> com.atguigu.pojo.Employee;<br><span class="hljs-keyword">import</span> com.atguigu.pojo.EmployeeExample;<br><span class="hljs-keyword">import</span> org.apache.ibatis.io.Resources;<br><span class="hljs-keyword">import</span> org.apache.ibatis.session.SqlSession;<br><span class="hljs-keyword">import</span> org.apache.ibatis.session.SqlSessionFactory;<br><span class="hljs-keyword">import</span> org.apache.ibatis.session.SqlSessionFactoryBuilder;<br><span class="hljs-keyword">import</span> org.junit.After;<br><span class="hljs-keyword">import</span> org.junit.Before;<br><span class="hljs-keyword">import</span> org.junit.Test;<br><br><span class="hljs-keyword">import</span> java.io.IOException;<br><span class="hljs-keyword">import</span> java.io.InputStream;<br><span class="hljs-keyword">import</span> java.util.List;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * 包名:com.atguigu</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> Leevi</span><br><span class="hljs-comment"> * 日期2021-08-28  14:06</span><br><span class="hljs-comment"> */</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestMybatis</span> </span>&#123;<br>    <span class="hljs-keyword">private</span> SqlSession sqlSession;<br>    <span class="hljs-keyword">private</span> EmployeeMapper employeeMapper;<br>    <span class="hljs-keyword">private</span> InputStream is;<br><br>    <span class="hljs-meta">@Before</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">init</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> IOException </span>&#123;<br>        <span class="hljs-comment">//目标:创建出EmployeeManager接口的代理对象</span><br>        <span class="hljs-comment">//1. 加载核心配置文件，转成字节输入流</span><br>        is = Resources.getResourceAsStream(<span class="hljs-string">&quot;mybatis-config.xml&quot;</span>);<br>        <span class="hljs-comment">//2. 创建SqlSessionFactoryBuilder对象</span><br>        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = <span class="hljs-keyword">new</span> SqlSessionFactoryBuilder();<br>        <span class="hljs-comment">//3. 构建出SqlSessionFactory</span><br>        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);<br>        <span class="hljs-comment">//4. 使用SqlSessionFactory对象创建出sqlSession对象</span><br>        sqlSession = sqlSessionFactory.openSession();<br>        <span class="hljs-comment">//5. 使用sqlSession对象创建UserMapper接口的代理对象</span><br>        employeeMapper = sqlSession.getMapper(EmployeeMapper.class);<br>    &#125;<br>    <span class="hljs-meta">@After</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">destroy</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> IOException </span>&#123;<br>        <span class="hljs-comment">//提交事务</span><br>        sqlSession.commit();<br>        <span class="hljs-comment">//关闭资源</span><br>        is.close();<br>        sqlSession.close();<br>    &#125;<br><br>    <span class="hljs-meta">@Test</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testInsertEmployee</span><span class="hljs-params">()</span></span>&#123;<br>        employeeMapper.insert(<span class="hljs-keyword">new</span> Employee(<span class="hljs-keyword">null</span>,<span class="hljs-string">&quot;王五&quot;</span>,<span class="hljs-number">3000d</span>));<br>    &#125;<br><br>    <span class="hljs-meta">@Test</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testDeleteEmployeeByPrimaryKey</span><span class="hljs-params">()</span></span>&#123;<br>        employeeMapper.deleteByPrimaryKey(<span class="hljs-number">15014</span>);<br>    &#125;<br><br>    <span class="hljs-meta">@Test</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testDeleteByExample</span><span class="hljs-params">()</span></span>&#123;<br>        <span class="hljs-comment">//根据较为复杂的条件进行删除，比如要删除empId在2000到8000之间的所有员工</span><br>        <span class="hljs-comment">//1. 创建一个EmployeeExample对象</span><br>        EmployeeExample employeeExample = <span class="hljs-keyword">new</span> EmployeeExample();<br>        <span class="hljs-comment">//2. 使用EmployeeExample对象获取criteria对象</span><br>        EmployeeExample.Criteria criteria = employeeExample.createCriteria();<br>        <span class="hljs-comment">//3. 通过criteria来拼接条件</span><br>        criteria.andEmpIdBetween(<span class="hljs-number">3000</span>,<span class="hljs-number">8000</span>);<br>        employeeMapper.deleteByExample(employeeExample);<br>    &#125;<br><br>    <span class="hljs-meta">@Test</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testUpdateEmployee</span><span class="hljs-params">()</span></span>&#123;<br>        employeeMapper.updateByPrimaryKeySelective(<span class="hljs-keyword">new</span> Employee(<span class="hljs-number">4</span>,<span class="hljs-keyword">null</span>,<span class="hljs-number">2000d</span>));<br>    &#125;<br><br>    <span class="hljs-meta">@Test</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testQueryByPrimaryKey</span><span class="hljs-params">()</span></span>&#123;<br>        <span class="hljs-comment">//根据主键查询</span><br>        Employee employee = employeeMapper.selectByPrimaryKey(<span class="hljs-number">4</span>);<br>        System.out.println(employee);<br>    &#125;<br><br>    <span class="hljs-meta">@Test</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testQueryAll</span><span class="hljs-params">()</span></span>&#123;<br>        EmployeeExample employeeExample = <span class="hljs-keyword">new</span> EmployeeExample();<br>        <span class="hljs-comment">//查询所有数据</span><br>        List&lt;Employee&gt; employeeList = employeeMapper.selectByExample(employeeExample);<br>    &#125;<br><br>    <span class="hljs-meta">@Test</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testQueryByExample</span><span class="hljs-params">()</span></span>&#123;<br>        <span class="hljs-comment">//复杂条件:查询(名字中包含s，并且大于3000)  或者 (emp_id在8001-8234之间,并且名字中包含3）的所有元素</span><br>        EmployeeExample employeeExample = <span class="hljs-keyword">new</span> EmployeeExample();<br>        EmployeeExample.Criteria criteria1 = employeeExample.createCriteria();<br>        criteria1.andEmpNameLike(<span class="hljs-string">&quot;%s%&quot;</span>)<br>                 .andEmpSalaryGreaterThan(<span class="hljs-number">3000d</span>);<br><br>        EmployeeExample.Criteria criteria2 = employeeExample.or();<br>        criteria2.andEmpIdBetween(<span class="hljs-number">8001</span>,<span class="hljs-number">8234</span>)<br>                 .andEmpNameLike(<span class="hljs-string">&quot;%3%&quot;</span>);<br>        employeeMapper.selectByExample(employeeExample);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h3 id="第四节-QBC查询"><a href="#第四节-QBC查询" class="headerlink" title="第四节  QBC查询"></a>第四节  QBC查询</h3><h4 id="1-概念"><a href="#1-概念" class="headerlink" title="1. 概念"></a>1. 概念</h4><p>QBC：Query By Criteria ， 最大的特点就是将SQL语句中的WHERE子句进行了组件化的封装，让我们可以通过调用Criteria对象的方法自由的拼装查询条件。 </p>
<h4 id="2-例子"><a href="#2-例子" class="headerlink" title="2. 例子"></a>2. 例子</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Test</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testQueryByExample</span><span class="hljs-params">()</span></span>&#123;<br>    <span class="hljs-comment">//复杂条件:查询(名字中包含s，并且大于3000)  或者 (emp_id在8001-8234之间,并且名字中包含3）的所有元素</span><br>    EmployeeExample employeeExample = <span class="hljs-keyword">new</span> EmployeeExample();<br>    EmployeeExample.Criteria criteria1 = employeeExample.createCriteria();<br>    criteria1.andEmpNameLike(<span class="hljs-string">&quot;%s%&quot;</span>)<br>        .andEmpSalaryGreaterThan(<span class="hljs-number">3000d</span>);<br><br>    EmployeeExample.Criteria criteria2 = employeeExample.or();<br>    criteria2.andEmpIdBetween(<span class="hljs-number">8001</span>,<span class="hljs-number">8234</span>)<br>        .andEmpNameLike(<span class="hljs-string">&quot;%3%&quot;</span>);<br>    employeeMapper.selectByExample(employeeExample);<br>&#125;<br><span class="hljs-comment">//实际执行的SQL语句:select emp_id, emp_name, emp_salary from t_emp WHERE ( emp_name like ? and emp_salary &gt; ? ) or( emp_id between ? and ? and emp_name like ? )</span><br></code></pre></td></tr></table></figure>

<h2 id="第三章-Mybatis的其它补充内容-了解"><a href="#第三章-Mybatis的其它补充内容-了解" class="headerlink" title="第三章 Mybatis的其它补充内容(了解)"></a>第三章 Mybatis的其它补充内容(了解)</h2><h3 id="第一节-插件机制"><a href="#第一节-插件机制" class="headerlink" title="第一节 插件机制"></a>第一节 插件机制</h3><h4 id="1-Mybatis四大对象"><a href="#1-Mybatis四大对象" class="headerlink" title="1. Mybatis四大对象"></a>1. Mybatis四大对象</h4><h5 id="1-1-Executor"><a href="#1-1-Executor" class="headerlink" title="1.1 Executor"></a>1.1 Executor</h5><p><img src="http://www.slx.blue/2021/12/03/mybatis04/tu_023.png" srcset="/img/loading.gif" lazyload></p>
<h5 id="1-2-ParameterHandler"><a href="#1-2-ParameterHandler" class="headerlink" title="1.2 ParameterHandler"></a>1.2 ParameterHandler</h5><p><img src="http://www.slx.blue/2021/12/03/mybatis04/tu_024.png" srcset="/img/loading.gif" lazyload></p>
<h5 id="2-3-ResultSetHandler"><a href="#2-3-ResultSetHandler" class="headerlink" title="2.3 ResultSetHandler"></a>2.3 ResultSetHandler</h5><p><img src="http://www.slx.blue/2021/12/03/mybatis04/tu_025.png" srcset="/img/loading.gif" lazyload></p>
<h5 id="2-4-StatementHandler"><a href="#2-4-StatementHandler" class="headerlink" title="2.4 StatementHandler"></a>2.4 StatementHandler</h5><p><img src="http://www.slx.blue/2021/12/03/mybatis04/tu_026.png" srcset="/img/loading.gif" lazyload></p>
<h4 id="2-Mybatis插件机制的作用"><a href="#2-Mybatis插件机制的作用" class="headerlink" title="2. Mybatis插件机制的作用"></a>2. Mybatis插件机制的作用</h4><p>插件是MyBatis提供的一个非常强大的机制，我们可以通过插件来修改MyBatis的一些核心行为。插件通过<strong>动态代理</strong>机制，可以介入四大对象的任何一个方法的执行。著名的Mybatis插件包括 PageHelper（分页插件）、通用 Mapper（SQL生成插件）等。</p>
<p>如果想编写自己的Mybatis插件可以通过实现org.apache.ibatis.plugin.Interceptor接口来完成，表示对Mybatis常规操作进行拦截，加入自定义逻辑。</p>
<p><img src="http://www.slx.blue/2021/12/03/mybatis04/tu_027.png" srcset="/img/loading.gif" lazyload></p>
<p> 但是由于插件涉及到Mybatis底层工作机制，在没有足够把握时不要轻易尝试。 </p>
<h3 id="第二节-Mybatis底层的JDBC封装"><a href="#第二节-Mybatis底层的JDBC封装" class="headerlink" title="第二节 Mybatis底层的JDBC封装"></a>第二节 Mybatis底层的JDBC封装</h3><p> org.apache.ibatis.executor.statement.PreparedStatementHandler类： </p>
<p><img src="http://www.slx.blue/2021/12/03/mybatis04/tu_028.png" srcset="/img/loading.gif" lazyload></p>
<p>查找上面目标时，Debug查看源码的切入点是：</p>
<p>org.apache.ibatis.session.defaults.DefaultSqlSession类的update()方法</p>
<p><img src="http://www.slx.blue/2021/12/03/mybatis04/tu_029.png" srcset="/img/loading.gif" lazyload></p>
<p>然后在分析<code>this.executor.update()方法</code></p>

            </div>
            <hr>
            <div>
              <div class="post-metas mb-3">
                
                  <div class="post-meta mr-3">
                    <i class="iconfont icon-category"></i>
                    
                      <a class="hover-with-bg" href="/categories/mybatis/">mybatis</a>
                    
                  </div>
                
                
                  <div class="post-meta">
                    <i class="iconfont icon-tags"></i>
                    
                      <a class="hover-with-bg" href="/tags/mybatis/">mybatis</a>
                    
                  </div>
                
              </div>
              
                <p class="note note-warning">
                  
                    本博客目前大部分文章都是参考尚硅谷或者马士兵教育的学习资料！<a href="http://www.atguigu.com/" rel="nofollow noopener"官网地址！</a> 
                  
                </p>
              
              
                <div class="post-prevnext">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/2021/12/03/IDEA_Import_SpringCode/">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">IDEA导入Spring源码</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/2021/12/03/javaDesignMode/">
                        <span class="hidden-mobile">java设计模式</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
              <!-- Comments -->
              <article class="comments" id="comments" lazyload>
                
                  
                
                

              </article>
            
          </article>
        </div>
      </div>
    </div>
    
      <div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
        <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p>
  <div class="toc-body" id="toc-body"></div>
</div>

      </div>
    
  </div>
</div>

<!-- Custom -->


    

    
      <a id="scroll-top-button" aria-label="TOP" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
    

    
  </main>

  <footer class="text-center mt-5 py-3">

  <div class="footer-content">
     <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a> <i class="iconfont icon-love"></i> <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a> 
	<!--《添加网站运行时间 -->
<br/>

<span id="timeDate">载入天数...</span><span id="times">载入时分秒...</span>
<script>
var now = new Date(); 

function createtime() {
    //此处修改你的建站时间或者网站上线时间
    var grt = new Date('11/02/2021 21:39:00');
    now.setTime(now.getTime() + 250);
    days = (now - grt) / 1000 / 60 / 60 / 24;

    dnum = Math.floor(days);
    hours = (now - grt) / 1000 / 60 / 60 - (24 * dnum);
    hnum = Math.floor(hours);
    if (String(hnum).length == 1) {
        hnum = "0" + hnum;
    }
    minutes = (now - grt) / 1000 / 60 - (24 * 60 * dnum) - (60 * hnum);
    mnum = Math.floor(minutes);
    if (String(mnum).length == 1) {
        mnum = "0" + mnum;
    }
    seconds = (now - grt) / 1000 - (24 * 60 * 60 * dnum) - (60 * 60 * hnum) - (60 * mnum);
    snum = Math.round(seconds);
    if (String(snum).length == 1) {
        snum = "0" + snum;
    }
    document.getElementById("timeDate").innerHTML = " 本站已各种夹缝中安全运行 " + dnum + " 天 ";
    document.getElementById("times").innerHTML = hnum + " 小时 " + mnum + " 分 " + snum + " 秒";
}
setInterval("createtime()", 250);
</script>

<!-- 添加网站运行时间》-->
  </div>
  
  <div class="statistics">
    
    

    
      
        <!-- 不蒜子统计PV -->
        <span id="busuanzi_container_site_pv" style="display: none">
            总访问量 
            <span id="busuanzi_value_site_pv"></span>
             次
          </span>
      
      
        <!-- 不蒜子统计UV -->
        <span id="busuanzi_container_site_uv" style="display: none">
            总访客数 
            <span id="busuanzi_value_site_uv"></span>
             人
          </span>
      
    
  </div>


  

  
</footer>


  <!-- SCRIPTS -->
  
  <script  src="https://cdn.jsdelivr.net/npm/nprogress@0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/nprogress@0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js" ></script>
<script  src="https://cdn.jsdelivr.net/npm/bootstrap@4/dist/js/bootstrap.min.js" ></script>
<script  src="/js/events.js" ></script>
<script  src="/js/plugins.js" ></script>

<!-- Plugins -->


  <script  src="/js/local-search.js" ></script>



  
    <script  src="/js/img-lazyload.js" ></script>
  



  



  
    <script  src="https://cdn.jsdelivr.net/npm/tocbot@4/dist/tocbot.min.js" ></script>
  
  
    <script  src="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3/dist/jquery.fancybox.min.js" ></script>
  
  
    <script  src="https://cdn.jsdelivr.net/npm/anchor-js@4/anchor.min.js" ></script>
  
  
    <script defer src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js" ></script>
  



  <script defer src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" ></script>




  <script  src="https://cdn.jsdelivr.net/npm/typed.js@2/lib/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var title = document.getElementById('subtitle').title;
      
      typing(title)
      
    })(window, document);
  </script>















<!-- 主题的启动项 保持在最底部 -->
<script  src="/js/boot.js" ></script>


</body>
</html>
